//
//  main.js
//
//  A project template for using arbor.js
//

(function($){

  var Renderer = function(canvas){
    var canvas = $(canvas).get(0)
    var ctx = canvas.getContext("2d");
    var gfx = arbor.Graphics(canvas)
    var particleSystem

    var that = {
      init:function(system){
        //
        // the particle system will call the init function once, right before the
        // first frame is to be drawn. it's a good place to set up the canvas and
        // to pass the canvas size to the particle system
        //
        // save a reference to the particle system for use in the .redraw() loop
        particleSystem = system

        // inform the system of the screen dimensions so it can map coords for us.
        // if the canvas is ever resized, screenSize should be called again with
        // the new dimensions
        particleSystem.screenSize(canvas.width, canvas.height) 
        particleSystem.screenPadding(80) // leave an extra 80px of whitespace per side
        
        // set up some event handlers to allow for node-dragging
        that.initMouseHandling()
      },
      
      redraw:function(){
        // 
        // redraw will be called repeatedly during the run whenever the node positions
        // change. the new positions for the nodes can be accessed by looking at the
        // .p attribute of a given node. however the p.x & p.y values are in the coordinates
        // of the particle system rather than the screen. you can either map them to
        // the screen yourself, or use the convenience iterators .eachNode (and .eachEdge)
        // which allow you to step through the actual node objects but also pass an
        // x,y point in the screen's coordinate system
        // 
        //ctx.fillStyle = "white"
        //ctx.fillRect(0,0, canvas.width, canvas.height)

        gfx.clear()
        
        particleSystem.eachEdge(function(edge, pt1, pt2){
          gfx.line(pt1, pt2, {stroke:"#b2b19d", width:2})
        })
        particleSystem.eachNode(function(node, pt){
          var w = Math.max(20, 20+gfx.textWidth(node.name) )
          if (node.data.alpha===0) return
          ctx.fillStyle = (node.data.alone) ? "orange" : "black"
          var alpha = node.data.alpha || 1
          if (node.data.shape=='dot'){
            var col = node.data.color||"#b2b19d"
            gfx.oval(pt.x-w/2, pt.y-w/2, w, w, {fill:col, alpha:alpha})
            gfx.text(node.name, pt.x, pt.y+7, {color:"white", align:"center", font:"Arial", size:12})
            gfx.text(node.name, pt.x, pt.y+7, {color:"white", align:"center", font:"Arial", size:12})
          }else{
            var col = node.data.color||"#a7af00"
            gfx.rect(pt.x-w/2, pt.y-8, w, 20, 4, {fill:col, alpha:alpha})
            gfx.text(node.name, pt.x, pt.y+9, {color:"white", align:"center", font:"Arial", size:12})
            gfx.text(node.name, pt.x, pt.y+9, {color:"white", align:"center", font:"Arial", size:12})
          }
        })

      /*  particleSystem.eachNode(function(node, pt){
          // node: {mass:#, p:{x,y}, name:"", data:{}}
          // pt:   {x:#, y:#}  node position in screen coords

          // draw a rectangle centered at pt
          var w = 10
          ctx.fillStyle = (node.data.alone) ? "orange" : "black"
          ctx.fillRect(pt.x-w/2, pt.y-w/2, w,w)
        })   */ 			
      },
      
      initMouseHandling:function(){
        // no-nonsense drag and drop (thanks springy.js)
        var dragged = null;

        // set up a handler object that will initially listen for mousedowns then
        // for moves and mouseups while dragging
        var handler = {
          clicked:function(e){
            var pos = $(canvas).offset();
            _mouseP = arbor.Point(e.pageX-pos.left, e.pageY-pos.top)
            dragged = particleSystem.nearest(_mouseP);

            if (dragged && dragged.node !== null){
              // while we're dragging, don't let physics move the node
              dragged.node.fixed = true
              if(dragged.node.data.links){
                for(var i=0; i<dragged.node.data.links.length; i++){
                  sys.addEdge(dragged.node,dragged.node.data.links[i])
                }
                dragged.node.data.links = false;
                dragged.node.data.color='orange';
              }
            }

            $(canvas).bind('mousemove', handler.dragged)
            $(window).bind('mouseup', handler.dropped)

            return false
          },
          dragged:function(e){
            var pos = $(canvas).offset();
            var s = arbor.Point(e.pageX-pos.left, e.pageY-pos.top)

            if (dragged && dragged.node !== null){
              var p = particleSystem.fromScreen(s)
              dragged.node.p = p
            }

            return false
          },

          dropped:function(e){
            if (dragged===null || dragged.node===undefined) return
            if (dragged.node !== null) dragged.node.fixed = false
            dragged.node.tempMass = 1000
            dragged = null
            $(canvas).unbind('mousemove', handler.dragged)
            $(window).unbind('mouseup', handler.dropped)
            _mouseP = null
            return false
          }
        }
        
        // start listening
        $(canvas).mousedown(handler.clicked);

      },
      
    }
    return that
  }    

  $(document).ready(function(){
    sys = arbor.ParticleSystem() // create the system with sensible repulsion/stiffness/friction
    //sys.parameters({gravity:true}) // use center-gravity to make the graph settle nicely (ymmv)
    sys.parameters({stiffness:900, repulsion:2000, gravity:true, dt:0.015})
    sys.renderer = Renderer("#viewport") // our newly created renderer will have its .init() method called shortly by sys...

    // add some nodes to the graph and watch it go...
    sys.addEdge('洪七公','黄蓉')
    sys.addEdge('郭靖','洪七公')
    sys.addEdge('郭靖','黄蓉')
    sys.addEdge('郭靖','丘处机')
    sys.addEdge('郭靖','周伯通')
    sys.addEdge('丘处机','王重阳')
    sys.addEdge('王重阳','周伯通')

    sys.addEdge('黄药师','黄蓉')

    sys.addNode('全真教', { shape:"dot", links:['王重阳','丘处机','周伯通']})
    sys.addNode('桃花岛', {shape:"dot", links:['黄药师','黄蓉']})
    sys.addNode('天下五绝', {shape:"dot", links:['黄药师','王重阳','洪七公']})
    sys.addNode('丐帮', {shape:"dot", links:['黄蓉','洪七公']})


    // or, equivalently:
    //
    // sys.graft({
    //   nodes:{
    //     "f":{alone:true, mass:.25,alpha:1}
    //   }, 
    //   edges:{
    //     "郭靖":{ "黄蓉":{},
    //         "丘处机":{"王重阳":{"周伯通":{"郭靖":{}}}},
    //         d:{},
    //         e:{}
    //     }
    //   }
    // })
    /*
    【王重阳】出生
    【洪七公】出生
    【周伯通】出生
    【王重阳】创立【全真教】
    【洪七公】执掌【丐帮】
    【黄药师】成为【桃花岛】岛主
    【周伯通】加入【全真教】
    【王重阳】、【洪七公】、【黄药师】 参与华山论剑，获得【天下五绝】称号
    【丘处机】出生
    【丘处机】加入【全真教】
    【郭靖】出生
    【黄蓉】出生并定居【桃花岛】
    【丘处机】传授【郭靖】武艺
    【郭靖】和【黄蓉】定情
    【洪七公】收【郭靖】、【黄蓉】为徒
    【郭靖】和【周伯通】结拜兄弟
    【黄蓉】接任【丐帮】帮主

    丐帮的小乞丐 向 全真教的小道士 借一笔钱
    */
    
  })

})(this.jQuery)